package com.bac.rentmap.ad.flat.user.view;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.flat.jdo.JdoHelper;
import com.bac.rentmap.ad.util.DateHelper;
import com.bac.rentmap.jdo.JdoSupport;

public class JdoViewStatisticsManager extends JdoSupport implements
        ViewStatisticsManager {
    private static final Logger log = Logger
            .getLogger(JdoViewStatisticsManager.class.getName());

    private int keepDaysCount;
    private DateHelper dateHelper;
    private JdoHelper jdoHelper;

    public void inc(long flatAdId, int count) {
        Date date = dateHelper.getDateForMidnight();
        inc(flatAdId, date, count);
    }

    void inc(long flatAdId, Date date, int count) {
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            log.finest("Incrementing statistics " + flatAdId + ", " + date + ", " + count);

            Query query = persistenceManager.newQuery(ViewStatistics.class);
            query.setFilter("flatAd == flatAdParam && date == dateParam");
            query.declareParameters("com.google.appengine.api.datastore.Key flatAdParam, java.util.Date dateParam");
            @SuppressWarnings("unchecked")
            List<ViewStatistics> viewStatisticsList = (List<ViewStatistics>) query
                    .execute(jdoHelper.convertToFlatAdKey(flatAdId), date);
            if (viewStatisticsList.isEmpty()) {
                log.finest("Creating ViewStatistics for " + flatAdId + ", "
                        + date);
                ViewStatistics viewStatistics = new ViewStatistics(
                        jdoHelper.convertToFlatAdKey(flatAdId), date);
                viewStatistics.inc(count);
                persistenceManager.makePersistent(viewStatistics);
            } else {
                ViewStatistics viewStatistics;
                if (viewStatisticsList.size() > 1) {
                    log.severe("More than one statistics entry found. Using first one.");
                }
                viewStatistics = viewStatisticsList.iterator().next();
                viewStatistics.inc(count);
                log.fine("Increamented to " + viewStatistics.getCount() + "(+" + count + ")");
            }
        } finally {
            persistenceManager.close();
        }
    }

    @Override
    public List<ViewStatistics> load(long flatAdId) {
        Date date = getThresholdDate();
        return load(flatAdId, date);
    }

    List<ViewStatistics> load(long flatAdId, Date date) {
        log.fine("Loading statistics " + flatAdId + ", " + date);
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            Query query = persistenceManager.newQuery(ViewStatistics.class);
            query.setFilter("flatAd == flatAdParam && date >= dateParam");
            query.declareParameters("com.google.appengine.api.datastore.Key flatAdParam, java.util.Date dateParam");
            query.setOrdering("date asc");

            @SuppressWarnings("unchecked")
            List<ViewStatistics> res = (List<ViewStatistics>) query.execute(
                    jdoHelper.convertToFlatAdKey(flatAdId), date);
            log.info("Loaded " + res.size() + " ViewStatistics for flatAd "
                    + flatAdId);
            return res;
        } finally {
            persistenceManager.close();
        }
    }

    private Date getThresholdDate() {
        return dateHelper.getDateForMidnight(-keepDaysCount);
    }

    @Override
    public int deleteOldStatistics() {
        Date date = getThresholdDate();
        log.fine("Deleting statistics older than " + date);
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            Query query = persistenceManager.newQuery(ViewStatistics.class);
            query.setFilter("date < dateParam");
            query.declareParameters("java.util.Date dateParam");
            int res = (int) query.deletePersistentAll(dateHelper
                    .getDateForMidnight(-keepDaysCount));
            log.fine("Deleted " + res + " ViewStatistics");
            return res;
        } finally {
            persistenceManager.close();
        }
    }

    @Required
    public void setKeepDaysCount(int keepDaysCount) {
        this.keepDaysCount = keepDaysCount;
    }

    @Required
    public void setDateHelper(DateHelper dateHelper) {
        this.dateHelper = dateHelper;
    }

    @Required
    public void setJdoHelper(JdoHelper jdoHelper) {
        this.jdoHelper = jdoHelper;
    }
}
